package xyz.mimai.media.netty.buf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;

/**
 * @ClassName BufDemo
 * @Description TODO
 * @Author 方丈
 * @Date 2021/2/7 9:10
 * @Version 1.0.0
 **/
public class BufDemo {
    public static void main(String[] args) {
        //m1();
//        m2();
        m3();
    }

    /**
     * https://www.cnblogs.com/crazymakercircle/p/9941658.html
     * ByteBuf 是Netty提供的一种数据结构，与java自带的NIO ByteBuffer有异曲同工之妙，但ByteBuf操作更简单方便，使用时，不需要进行模式切换，而ByteBuffer在读写方式
     * 转换时，必须先调用flip()方法。究其原因在于ByteBuf维护了readIndex和writeIndex各自记录保存读写位置，而不像ByteBuffer只有一个index记录当前操作位置。
     *
     * 第1种操作ByteBuf的方式
     * 写入：通过writeByte逐位写入,writeIndex逐步增加
     * 读取：通过指定下标，getByte对应位置元素，这种读取的方式并没有使用readIndex，它的readIndex一直是0
     */
    public static void m1(){
        ByteBuf bf = Unpooled.buffer(16);

        for(int x = 0;x<bf.capacity();x++){
            bf.writeByte(x*2);
            System.out.println("writeIndex:"+bf.writerIndex());
        }

        for(int x = 0;x<bf.capacity();x++){
            System.out.println("第"+(x+1)+"位:"+bf.getByte(x)+", readIndex:"+bf.readerIndex());
        }
    }

    /**
     * 第2中操作方式
     * 写入：直接指定编码，将字符串一次性写入ByteBuf对象，这种写入方式应该是使用场景最多的一种方式
     * 读取：ByteBuf的底层其实维护了一个array，将array中的所有内容整体构建一个字符串对象进行读取，这种读取方式readerIndex还是不会变，读取前后都是0
     */
    public static void m2(){
        ByteBuf bf = Unpooled.copiedBuffer("hello,ByteBuf", CharsetUtil.UTF_8);
        if(bf.hasArray()){
            System.out.println("writerIndex="+bf.writerIndex());
            System.out.println("readerIndex="+bf.readerIndex());
            byte[] array = bf.array();
            String content = new String(array,CharsetUtil.UTF_8);
            System.out.println("content="+content);

            System.out.println("arrayOffset="+bf.arrayOffset());
            System.out.println("writerIndex="+bf.writerIndex());
            System.out.println("readerIndex="+bf.readerIndex());
            System.out.println("readableBytes="+bf.readableBytes());
        }
    }

    /**
     * 第三种操作方式：
     * 通过readByte方法读取，这样readerIndex是会逐步递增的，另外需要注意的是，循环读取的时候不能使用capacity()方法限制下标，writerIndex()方法才是实际指向内容末尾的位置。
     * capacity()是申请内存的大小，不一定和实际的写入一致
     * resetReaderIndex()可以重新初始化readIndex，这样又是从开始位置读取buf。一次读取后，想重新读buf可以调用该方法复位。
     * resetWriterIndex()也是类似的,调用该方法后，会重头覆盖写入
     */
    public static void m3(){
        ByteBuf bf = Unpooled.copiedBuffer("hello,ByteBuf", CharsetUtil.UTF_8);
        for(int x = 0;x<bf.writerIndex();x++){
            System.out.println("第"+(x+1)+"位:"+(char)bf.readByte()+", readIndex:"+bf.readerIndex()+",  capacity="+bf.capacity());
        }
        System.out.println("readIndex:"+bf.readerIndex()+",  capacity="+bf.capacity());
        bf.resetReaderIndex();

        for(int x = 0;x<bf.writerIndex();x++){
            System.out.println("第"+(x+1)+"位:"+(char)bf.readByte()+", readIndex:"+bf.readerIndex()+",  capacity="+bf.capacity());
        }
    }
}
